// 游戏网格数据模型
export class GameBoard {
    constructor(width = 8, height = 8) {
        this.width = width;
        this.height = height;
        this.grid = [];
        this.initializeGrid();
    }

    // 初始化8x8网格
    initializeGrid() {
        this.grid = [];
        for (let x = 0; x < this.width; x++) {
            this.grid[x] = [];
            for (let y = 0; y < this.height; y++) {
                this.grid[x][y] = this.createCell(x, y, 0);
            }
        }
        // 填充随机小鬼类型，确保无初始匹配
        this.fillGridWithoutMatches();
    }

    // 创建单元格数据模型
    createCell(x, y, type) {
        return {
            type: type,           // 小鬼类型 (0-4)
            id: `cell-${x}-${y}`, // 唯一标识符
            x: x,                 // 网格X坐标
            y: y,                 // 网格Y坐标
            element: null         // DOM元素引用，稍后设置
        };
    }

    // 获取指定位置的单元格
    getCell(x, y) {
        if (this.isValidPosition(x, y)) {
            return this.grid[x][y];
        }
        return null;
    }

    // 设置指定位置的单元格
    setCell(x, y, cell) {
        if (this.isValidPosition(x, y)) {
            this.grid[x][y] = cell;
            return true;
        }
        return false;
    }

    // 设置指定位置的小鬼类型
    setCellType(x, y, type) {
        const cell = this.getCell(x, y);
        if (cell) {
            cell.type = type;
            return true;
        }
        return false;
    }

    // 验证坐标是否有效
    isValidPosition(x, y) {
        return x >= 0 && x < this.width && y >= 0 && y < this.height;
    }

    // 交换两个单元格的位置
    swapCells(pos1, pos2) {
        const cell1 = this.getCell(pos1.x, pos1.y);
        const cell2 = this.getCell(pos2.x, pos2.y);
        
        if (cell1 && cell2) {
            // 交换类型
            const tempType = cell1.type;
            cell1.type = cell2.type;
            cell2.type = tempType;
            return true;
        }
        return false;
    }

    // 获取相邻单元格
    getAdjacentCells(x, y) {
        const adjacent = [];
        const directions = [
            { dx: -1, dy: 0 }, // 左
            { dx: 1, dy: 0 },  // 右
            { dx: 0, dy: -1 }, // 上
            { dx: 0, dy: 1 }   // 下
        ];

        directions.forEach(dir => {
            const newX = x + dir.dx;
            const newY = y + dir.dy;
            const cell = this.getCell(newX, newY);
            if (cell) {
                adjacent.push(cell);
            }
        });

        return adjacent;
    }

    // 检查两个位置是否相邻
    areAdjacent(pos1, pos2) {
        const dx = Math.abs(pos1.x - pos2.x);
        const dy = Math.abs(pos1.y - pos2.y);
        return (dx === 1 && dy === 0) || (dx === 0 && dy === 1);
    }

    // 获取整个网格的副本
    getGridCopy() {
        const copy = [];
        for (let x = 0; x < this.width; x++) {
            copy[x] = [];
            for (let y = 0; y < this.height; y++) {
                copy[x][y] = { ...this.grid[x][y] };
            }
        }
        return copy;
    }

    // 清空指定位置的单元格
    clearCell(x, y) {
        const cell = this.getCell(x, y);
        if (cell) {
            cell.type = -1; // -1 表示空单元格
            return true;
        }
        return false;
    }

    // 检查单元格是否为空
    isEmpty(x, y) {
        const cell = this.getCell(x, y);
        return cell && cell.type === -1;
    }

    // 生成随机小鬼类型 (0-4，共5种类型)
    getRandomGhostType() {
        return Math.floor(Math.random() * 5);
    }

    // 获取安全的随机类型（避免在指定位置产生匹配）
    getSafeRandomType(x, y) {
        const forbiddenTypes = new Set();
        
        // 检查水平方向的潜在匹配
        const leftTypes = [];
        for (let i = x - 1; i >= Math.max(0, x - 2); i--) {
            const cell = this.getCell(i, y);
            if (cell && cell.type >= 0) {
                leftTypes.push(cell.type);
            } else {
                break;
            }
        }
        
        // 如果左边有两个相同类型，禁用该类型
        if (leftTypes.length >= 2 && leftTypes[0] === leftTypes[1]) {
            forbiddenTypes.add(leftTypes[0]);
        }

        // 检查垂直方向的潜在匹配
        const upTypes = [];
        for (let i = y - 1; i >= Math.max(0, y - 2); i--) {
            const cell = this.getCell(x, i);
            if (cell && cell.type >= 0) {
                upTypes.push(cell.type);
            } else {
                break;
            }
        }
        
        // 如果上面有两个相同类型，禁用该类型
        if (upTypes.length >= 2 && upTypes[0] === upTypes[1]) {
            forbiddenTypes.add(upTypes[0]);
        }

        // 生成不在禁用列表中的随机类型
        let type;
        let attempts = 0;
        do {
            type = this.getRandomGhostType();
            attempts++;
            // 防止无限循环
            if (attempts > 20) {
                break;
            }
        } while (forbiddenTypes.has(type) && forbiddenTypes.size < 5);

        return type;
    }

    // 填充网格，确保无初始匹配
    fillGridWithoutMatches() {
        for (let y = 0; y < this.height; y++) {
            for (let x = 0; x < this.width; x++) {
                const safeType = this.getSafeRandomType(x, y);
                this.setCellType(x, y, safeType);
            }
        }
    }

    // 重新生成网格
    regenerateGrid() {
        this.initializeGrid();
    }

    // 填充空单元格
    fillEmptySpaces() {
        const newCells = [];
        
        for (let x = 0; x < this.width; x++) {
            // 应用重力，让非空单元格下落
            const column = [];
            for (let y = this.height - 1; y >= 0; y--) {
                const cell = this.getCell(x, y);
                if (cell && cell.type >= 0) {
                    column.push(cell.type);
                }
            }
            
            // 填充列
            let writeIndex = this.height - 1;
            
            // 先放置现有的非空单元格
            for (let i = 0; i < column.length; i++) {
                this.setCellType(x, writeIndex, column[i]);
                writeIndex--;
            }
            
            // 在顶部生成新的随机单元格
            while (writeIndex >= 0) {
                const newType = this.getSafeRandomType(x, writeIndex);
                this.setCellType(x, writeIndex, newType);
                newCells.push({ x, y: writeIndex, type: newType });
                writeIndex--;
            }
        }
        
        return newCells;
    }

    // 查找所有匹配
    findMatches() {
        const matches = [];
        const horizontalMatches = this.findHorizontalMatches();
        const verticalMatches = this.findVerticalMatches();
        
        matches.push(...horizontalMatches);
        matches.push(...verticalMatches);
        
        return this.mergeOverlappingMatches(matches);
    }

    // 查找水平匹配
    findHorizontalMatches() {
        const matches = [];
        
        for (let y = 0; y < this.height; y++) {
            let count = 1;
            let currentType = this.grid[0][y].type;
            let startX = 0;
            
            for (let x = 1; x < this.width; x++) {
                const cellType = this.grid[x][y].type;
                
                if (cellType === currentType && cellType >= 0) {
                    count++;
                } else {
                    // 检查是否形成匹配（3个或更多）
                    if (count >= 3 && currentType >= 0) {
                        matches.push(this.createMatch(startX, y, count, 'horizontal', currentType));
                    }
                    
                    // 重置计数
                    count = 1;
                    currentType = cellType;
                    startX = x;
                }
            }
            
            // 检查行末尾的匹配
            if (count >= 3 && currentType >= 0) {
                matches.push(this.createMatch(startX, y, count, 'horizontal', currentType));
            }
        }
        
        return matches;
    }

    // 查找垂直匹配
    findVerticalMatches() {
        const matches = [];
        
        for (let x = 0; x < this.width; x++) {
            let count = 1;
            let currentType = this.grid[x][0].type;
            let startY = 0;
            
            for (let y = 1; y < this.height; y++) {
                const cellType = this.grid[x][y].type;
                
                if (cellType === currentType && cellType >= 0) {
                    count++;
                } else {
                    // 检查是否形成匹配（3个或更多）
                    if (count >= 3 && currentType >= 0) {
                        matches.push(this.createMatch(x, startY, count, 'vertical', currentType));
                    }
                    
                    // 重置计数
                    count = 1;
                    currentType = cellType;
                    startY = y;
                }
            }
            
            // 检查列末尾的匹配
            if (count >= 3 && currentType >= 0) {
                matches.push(this.createMatch(x, startY, count, 'vertical', currentType));
            }
        }
        
        return matches;
    }

    // 创建匹配对象
    createMatch(startX, startY, length, direction, type) {
        const cells = [];
        
        if (direction === 'horizontal') {
            for (let i = 0; i < length; i++) {
                cells.push({ x: startX + i, y: startY });
            }
        } else { // vertical
            for (let i = 0; i < length; i++) {
                cells.push({ x: startX, y: startY + i });
            }
        }
        
        return {
            cells: cells,
            type: type,
            direction: direction,
            length: length
        };
    }

    // 合并重叠的匹配
    mergeOverlappingMatches(matches) {
        if (matches.length <= 1) return matches;
        
        const cellsToRemove = new Set();
        
        // 收集所有需要移除的单元格
        matches.forEach(match => {
            match.cells.forEach(cell => {
                cellsToRemove.add(`${cell.x},${cell.y}`);
            });
        });
        
        // 创建合并后的匹配对象
        const mergedCells = Array.from(cellsToRemove).map(cellStr => {
            const [x, y] = cellStr.split(',').map(Number);
            return { x, y };
        });
        
        if (mergedCells.length >= 3) {
            return [{
                cells: mergedCells,
                type: matches[0].type, // 使用第一个匹配的类型
                direction: 'mixed',
                length: mergedCells.length
            }];
        }
        
        return matches;
    }

    // 移除匹配的单元格
    removeMatches(matches) {
        const removedCells = [];
        
        matches.forEach(match => {
            match.cells.forEach(cell => {
                if (this.getCell(cell.x, cell.y)) {
                    this.clearCell(cell.x, cell.y);
                    removedCells.push(cell);
                }
            });
        });
        
        return removedCells;
    }

    // 检查交换是否有效（会产生匹配）
    isValidSwap(pos1, pos2) {
        // 检查是否相邻
        if (!this.areAdjacent(pos1, pos2)) {
            return false;
        }
        
        // 临时交换
        this.swapCells(pos1, pos2);
        
        // 检查是否产生匹配
        const matches = this.findMatches();
        const hasMatches = matches.length > 0;
        
        // 恢复交换
        this.swapCells(pos1, pos2);
        
        return hasMatches;
    }

    // 应用重力效果
    applyGravity() {
        const moves = [];
        
        for (let x = 0; x < this.width; x++) {
            let writeIndex = this.height - 1;
            
            // 从底部向上扫描
            for (let y = this.height - 1; y >= 0; y--) {
                const cell = this.getCell(x, y);
                if (cell && cell.type >= 0) {
                    if (y !== writeIndex) {
                        // 记录移动
                        moves.push({
                            from: { x, y },
                            to: { x, y: writeIndex }
                        });
                        
                        // 移动单元格
                        this.setCellType(x, writeIndex, cell.type);
                        this.clearCell(x, y);
                    }
                    writeIndex--;
                }
            }
        }
        
        return moves;
    }

    // 打印网格状态（调试用）
    printGrid() {
        console.log('当前网格状态:');
        for (let y = 0; y < this.height; y++) {
            let row = '';
            for (let x = 0; x < this.width; x++) {
                row += this.grid[x][y].type + ' ';
            }
            console.log(row);
        }
    }
}